package gosee

import (
	"encoding/json"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"os"
)

// H 自定义类型表示键值对数据
type H map[string]any

// Context 上下文结构体
type Context struct {
	// 原始对象
	Writer  http.ResponseWriter
	Request *http.Request
	// 响应信息
	StatusCode int

	UrlParams map[string]string

	// 中间件数据
	Middleware *Middleware

	Engine *Engine
}

// 构造函数
func newContext(w http.ResponseWriter, r *http.Request) *Context {
	return &Context{
		Writer:     w,
		Request:    r,
		UrlParams:  make(map[string]string),
		Middleware: NewMiddleware(),
	}
}

// 参数获取方法
func (c *Context) PostForm(key string) string {
	return c.Request.FormValue(key)
}

func (c *Context) Query(key string) string {
	return c.Request.URL.Query().Get(key)
}

func (c *Context) Param(key string) string {
	if c.Request == nil {
		return ""
	}

	if val := c.PostForm(key); val != "" {
		return val
	}

	return c.Query(key)
}

// 获取路由参数
func (c *Context) GetUrlParam(key string) string {
	return c.UrlParams[key]
}

// 响应控制方法
func (c *Context) Status(code int) {
	c.StatusCode = code
	c.Writer.WriteHeader(code)
}

func (c *Context) SetHeader(key, value string) {
	c.Writer.Header().Set(key, value)
}

func (c *Context) SetContentType(value string) {
	c.SetHeader("Content-Type", value)
}

// 响应格式化方法
func (c *Context) String(code int, format string, values ...any) {
	c.SetContentType("text/plain; charset=utf-8")
	c.Status(code)
	c.Writer.Write(fmt.Appendf(nil, format, values...))
}

func (c *Context) JSON(code int, obj any) {
	c.SetContentType("application/json")
	c.Status(code)
	enc := json.NewEncoder(c.Writer)
	if err := enc.Encode(obj); err != nil {
		http.Error(c.Writer, err.Error(), 500)
	}
}

func (c *Context) Data(code int, data []byte) {
	c.Status(code)
	c.Writer.Write(data)
}

func (c *Context) HTML(code int, html string) {
	c.SetContentType("text/plain; charset=utf-8")
	c.Status(code)
	c.Writer.Write([]byte(html))
}

func (c *Context) Fail(code int, err string) {
	c.Middleware.index = len(c.Middleware.handlers)
	c.JSON(code, H{"message": err})
}

func (c *Context) Next() {
	c.Middleware.Next(c)
}

func (c *Context) View(view string, data ...any) {
	if len(data) > 1 {
		panic("View() 只能接受 0 或 1 个参数")
	}

	var tmplData map[string]any
	if len(data) == 1 {
		if d, ok := data[0].(map[string]any); ok {
			tmplData = d
		} else {
			panic("参数必须是 map[string]any")
		}
	} else {
		tmplData = nil // 默认空数据
	}

	if err := c.Engine.Template.Templates.ExecuteTemplate(c.Writer, view, tmplData); err != nil {
		c.String(http.StatusInternalServerError, "Template execution error: %v", err)
		return
	}
}

// func (c *Context) MultipartForm() (*multipart.Form, error) {
// 	c.Request.Request.ParseMultipartForm()
// 	return c.Request.Request.MultipartForm, err
// }

func (c *Context) MultipartForm() (*multipart.Form, error) {
	// 如果 MultipartForm 已解析，直接返回
	if c.Request.MultipartForm != nil {
		return c.Request.MultipartForm, nil
	}

	// 解析 multipart 表单
	if err := c.Request.ParseMultipartForm(c.Engine.MaxMultipartMemory); err != nil {
		return nil, err
	}

	return c.Request.MultipartForm, nil
}

// 单文件上传
func (c *Context) FormFile(name string) (*multipart.FileHeader, error) {
	_, fileHeader, err := c.Request.FormFile(name)
	if err != nil {
		return nil, err
	}

	return fileHeader, nil
}

// 保存文件(文件,存储路径)
// 保存上传文件（基于文件头）
func (c *Context) SaveUploadedFile(fileHeader *multipart.FileHeader, path string) error {
	if fileHeader == nil {
		return nil // 防止空指针
	}

	// 打开上传文件流
	file, err := fileHeader.Open()
	if err != nil {
		return err
	}
	defer file.Close()

	// 创建目标文件
	dst, err := os.Create(path)
	if err != nil {
		return err
	}
	defer dst.Close()

	// 将上传内容复制到目标文件
	if _, err := io.Copy(dst, file); err != nil {
		return err
	}

	return nil
}
